package com.inspur.edp.bef.bemanager.service;


import com.inspur.edp.bef.bemanager.codegenerator.JavaCodeFileGenerator;
import com.inspur.edp.bef.bemanager.codegenerator.genutils.BeCommonUtilsGenerator;
import com.inspur.edp.bef.bemanager.generatecomponent.ComponentGenerator;
import com.inspur.edp.bef.bemanager.generatedbo.DboGenerater;
import com.inspur.edp.bef.bemanager.util.CheckInfoUtil;
import com.inspur.edp.bef.bizentity.GspBizEntityElement;
import com.inspur.edp.bef.bizentity.GspBusinessEntity;
import com.inspur.edp.bef.bizentity.beenum.BECategory;
import com.inspur.edp.bef.bizentity.dtservice.IBizEntityDtService;
import com.inspur.edp.bef.bizentity.exceptions.BusinessEntityErrorCodeEnum;
import com.inspur.edp.bef.bizentity.exceptions.BusinessEntityException;
import com.inspur.edp.bef.bizentity.operation.BizOperation;
import com.inspur.edp.bef.component.base.GspComponent;
import com.inspur.edp.cef.designtime.api.element.EnumIndexType;
import com.inspur.edp.cef.designtime.api.element.GspElementObjectType;
import com.inspur.edp.cef.designtime.api.entity.MappingInfo;
import com.inspur.edp.cef.designtime.api.util.MetadataUtil;
import com.inspur.edp.das.commonmodel.IGspCommonObject;
import com.inspur.edp.formserver.viewmodel.GspViewModel;
import com.inspur.edp.formserver.viewmodel.common.ConvertUtils;
import com.inspur.edp.jittojava.context.GenerateService;
import com.inspur.edp.lcm.databaseobject.api.DatabaseObjectServiceForWebIde;
import com.inspur.edp.lcm.metadata.api.IMetadataContent;
import com.inspur.edp.lcm.metadata.api.entity.GspMetadata;
import com.inspur.edp.lcm.metadata.api.entity.MetadataProject;
import com.inspur.edp.lcm.metadata.api.entity.ProcessMode;
import com.inspur.edp.lcm.metadata.api.service.FileService;
import com.inspur.edp.lcm.metadata.api.service.MetadataProjectService;
import com.inspur.edp.lcm.metadata.api.service.MetadataService;
import com.inspur.edp.lcm.metadata.devcommon.ManagerUtils;
import com.inspur.edp.sgf.api.common.ResourceType;
import com.inspur.edp.sgf.api.service.EapiMetadataDtService;
import com.inspur.edp.udt.designtime.api.entity.SimpleDataTypeDef;
import com.inspur.edp.udt.designtime.api.entity.UnifiedDataTypeDef;
import io.iec.edp.caf.commons.utils.SpringBeanUtils;

import java.io.File;
import java.util.ArrayList;
import java.util.Objects;
import java.util.UUID;
import java.util.regex.Matcher;
import org.springframework.util.StringUtils;

public class BeManagerService implements IBizEntityDtService {

    private  static MetadataService metadataService;
    public static  MetadataService getMetadataService(){
        if(metadataService==null)
            metadataService=SpringBeanUtils.getBean(MetadataService.class);
        return metadataService;
    }
    public static void saveMetadata(GspMetadata metadata, String metadataPath) {
        getMetadataService().saveMetadata(metadata, CheckInfoUtil.getCombinePath(metadataPath, metadata.getHeader().getFileName()));
    }
    // 工程路径

    public static String getProjPath(String relativePath) {
        MetadataProjectService service = getMetadataProjectService();
        return service.getProjPath(relativePath);
    }

    private static  MetadataProjectService metadataProjectService;
    public static MetadataProjectService getMetadataProjectService() {
        if(metadataProjectService == null) {
            metadataProjectService = SpringBeanUtils.getBean(MetadataProjectService.class);
        }
        return metadataProjectService;
    }

    private static GenerateService generateService;
    public static GenerateService getGenerateService() {
        if(generateService == null) {
            generateService = SpringBeanUtils.getBean(GenerateService.class);
        }
        return generateService;
    }


    public static void generateDbo(GspMetadata metadata, String metadataPath, boolean isSave) {
        GspBusinessEntity be = (GspBusinessEntity) ((metadata.getContent() instanceof GspBusinessEntity) ? metadata.getContent() : null);
        if (be.getCategory() == BECategory.DependentBusinessEntity) {
            return;
        }
        DboGenerater dboGenerater = new DboGenerater(metadataPath);
        dboGenerater.GenerateDboFromBizEntity(be, metadataPath);

        if (isSave) {
            saveMetadata(metadata, metadataPath);
        }
    }

    public static ArrayList<String> generateComponent(GspMetadata metadata, String metadataPath, boolean isSave) {
         return ComponentGenerator.getInstance().generateComponent(metadata, metadataPath);
    }

    public static void generateComponentCode(GspMetadata metadata, String metadataPath, ArrayList<String> actionList) {
        String ProjectPath = metadata.getRelativePath();
        //ProjectPath = ProjectPath.Remove(ProjectPath.LastIndexOf("/"), ProjectPath.Length - (ProjectPath.LastIndexOf("/")));
        new JavaCodeFileGenerator(metadata).generate(actionList);
        new BeCommonUtilsGenerator((GspBusinessEntity) metadata.getContent(),metadata).generateCommonUtils();
    }

    private boolean isHasComp(){
        return false;
    }

    /**
     * 判断当前是否创建Java模板，创建返回值为true,不能创建返回flase;
     *
     * @param
     * @return
     */
    public static boolean CreatJavaModule(String ProjectPath) {
        return true;
    }

    /**
     * 判断当前是否创建dotnet模板，创建返回值为true,不能创建返回flase;
     *
     * @param
     * @return
     */
    public static boolean CreatDotnetModule(String ProjectPath) {
        return false;
    }

    public static void preBuild(GspMetadata metadata, String metadataPath) {
        //BEGeneratorService service = new BEGeneratorService();
        //service.PreGenerate(metadataPath, metadata);

        try {
            SpringBeanUtils.getBean(GenerateService.class).generateApi(metadataPath);
        } catch (Exception e) {
            throw BusinessEntityException.createException(BusinessEntityErrorCodeEnum.GSP_BEMODEL_BUSINESS_ENTITY_0083, e);
        }
//		ServiceManager.<MetadataJitService>GetService().GenerateApi(metadataPath);
    }

    public static void build(GspMetadata metadata, String metadataPath) {
        build(metadata, metadataPath, null);
    }

    public static void build(GspMetadata metadata, String metadataPath, String serverPath) {
        throw BusinessEntityException.createException(BusinessEntityErrorCodeEnum.GSP_BEMODEL_COMMON_0006, "BeManagerService", "build");
    }

    public static void publish(GspMetadata metadata, String metadataPath) {
        GspBusinessEntity be = (GspBusinessEntity) ((metadata.getContent() instanceof GspBusinessEntity) ? metadata.getContent() : null);

        if (be.getCategory() != BECategory.DependentBusinessEntity) {
            DeployDbo(be, metadataPath);
        }
        //Build(metadata, metadataPath);
    }

    /**
     * 发布dbo
     *
     * @param be
     * @param path
     */
    private static void DeployDbo(GspBusinessEntity be, String path) {
        DatabaseObjectServiceForWebIde service = SpringBeanUtils.getBean(DatabaseObjectServiceForWebIde.class);

        service.deployDatabaseObject(path, be.getMainObject().getRefObjectName());

        if (be.getMainObject().getContainChildObjects() == null || be.getMainObject().getContainChildObjects().size() < 1) {
            return;
        }
        for (IGspCommonObject childObject : be.getMainObject().GetAllChildObjects()) {
            service.deployDatabaseObject(path, childObject.getRefObjectName());
        }
    }

    public static void publishService(GspMetadata metadata, String metadataPath) {
        createViewMode(metadata, metadataPath);
    }

    ///#region Vm&Service
    private static final String VmSuffix = "Service";

    private static void createViewMode(GspMetadata metadata, String path) {
        String metadataName = metadata.getHeader().getCode();
        //var be = metadata.Content as GspBusinessEntity;
        String vmPath = getVmPath(path);
        MetadataService service = SpringBeanUtils.getBean(MetadataService.class);
        String vmFileName = String.format("%1$s%2$s.vo", metadataName, VmSuffix);

        GspMetadata vmMetadata;
        if (service.isMetadataExist(vmPath, vmFileName)) {
            vmMetadata = updateViewModel(metadata, vmFileName, vmPath, service);
        } else {
            vmMetadata = createViewMode(metadata, metadataName, vmPath, service);
        }

        //VmGeneratorService.Generate(vmPath, vmMetadata);
        EapiMetadataDtService eapiService = SpringBeanUtils.getBean(EapiMetadataDtService.class);

        eapiService.create(vmMetadata, vmPath, ResourceType.VO_ADVANCE);
    }

    private static String getVmPath(String path) {
        MetadataProject projectInfo = SpringBeanUtils.getBean(MetadataProjectService.class).getMetadataProjInfo(path);
        String projectPath = projectInfo.getProjectPath();
        //var vmPath = Path.Combine(projectPath, "form", metadataName.ToLower(), "bff");

        String vmPath = CheckInfoUtil.getCombinePath(projectPath, "bff");

        FileService fileService = SpringBeanUtils.getBean(FileService.class);
        if (!fileService.isDirectoryExist(vmPath)) {
            fileService.createDirectory(vmPath);
        }

        return vmPath;
    }

    private static GspMetadata updateViewModel(GspMetadata metadata, String vmFileName, String vmPath, MetadataService service) {

        GspBusinessEntity be = (GspBusinessEntity) ((metadata.getContent() instanceof GspBusinessEntity) ? metadata.getContent() : null);
        GspMetadata vmMetadata = service.loadMetadata(vmFileName, vmPath);
        GspViewModel vm = ConvertUtils.convertToViewModel(be, "", metadata.getHeader().getId());
        vm.setID(vmMetadata.getHeader().getId());
        vmMetadata.setContent(vm);
        service.saveMetadata(vmMetadata, CheckInfoUtil.getCombinePath(vmPath, vmFileName));

        return vmMetadata;
    }

    private static GspMetadata createViewMode(GspMetadata metadata, String metadataName, String vmPath, MetadataService service) {

        GspBusinessEntity be = (GspBusinessEntity) ((metadata.getContent() instanceof GspBusinessEntity) ? metadata.getContent() : null);
        GspViewModel vm = ConvertUtils.convertToViewModel(be, "", metadata.getHeader().getId());
        GspMetadata vmMetadata = new GspMetadata();

        vmMetadata.setHeader(metadata.getHeader());
        vmMetadata.getHeader().setId("");
        vmMetadata.getHeader().setCode(String.format("%1$s%2$s", metadataName, VmSuffix));
        vmMetadata.getHeader().setName(vm.getName());
        vmMetadata.getHeader().setType("GspViewModel");
        vmMetadata = service.initializeMetadataEntity(vmMetadata);

        vm.setID(vmMetadata.getHeader().getId());
        vmMetadata.setContent(vm);

        service.createMetadata(vmPath, vmMetadata);
        return vmMetadata;
    }


    public static void Deploy(String metadataPath) {


//		var metadataProj = ServiceManager.<IMetadataProjectService>GetService().GetMetadataProjInfo(metadataPath);
//		String projectPath = Path.Combine(PathTransform.GetUserProjectsRoot(), metadataProj.ProjectPath).Replace("\\","/");
//		String deployToolPath = Path.Combine(GspEnvironment.RootPath, "platform/dev/main/libs/BefDeployer.dll").Replace("\\","/");
//
//		//IsProjectExists(projectPath);
//		//var command = "../netcore/windows/dotnet.exe";
//		String command = "dotnet";
//		ProcessStartInfo tempVar = new ProcessStartInfo(command, " " + deployToolPath + " -s " + projectPath);
//		tempVar.CreateNoWindow = false;
//		tempVar.UseShellExecute = true;
//		tempVar.ErrorDialog = true;
//		tempVar.WorkingDirectory = Path.GetFullPath(Path.Combine(GspEnvironment.RootPath, "platform/dev/main/libs/")).Replace("\\", "/");
//		ProcessStartInfo psi = tempVar;
//			//RedirectStandardInput = false,
//			//RedirectStandardOutput = false,
//			//RedirectStandardError = true,
//		Process.Start(psi);
    }

    ///#region IBizEntityDtService
    public void generateDbo(GspMetadata metadata, String metadataPath) {
        generateDbo(metadata, metadataPath, true);
    }

    @Override
    public GspBizEntityElement createUdtElement(String id, String code, String name, String labelId,
        String udtId) {
        Objects.requireNonNull(code, "code");
        Objects.requireNonNull(name, "name");
        Objects.requireNonNull(labelId, "labelId");
        Objects.requireNonNull(udtId, "udtId");

        if(StringUtils.isEmpty(id)) {
            id = UUID.randomUUID().toString();
        }

        GspMetadata metadata = MetadataUtil.getCustomMetadata(udtId);
        if(metadata == null) {
            throw BusinessEntityException.createException(BusinessEntityErrorCodeEnum.GSP_BEMODEL_BUSINESS_ENTITY_0010, udtId);
        }
        UnifiedDataTypeDef udtDef = (UnifiedDataTypeDef) metadata.getContent();
        if(udtDef == null) {
            throw BusinessEntityException.createException(BusinessEntityErrorCodeEnum.GSP_BEMODEL_BUSINESS_ENTITY_0010, udtId);
        }
        if(!(udtDef instanceof SimpleDataTypeDef)) {
            throw BusinessEntityException.createException(BusinessEntityErrorCodeEnum.GSP_BEMODEL_BUSINESS_ENTITY_0011, udtDef.getName());
        }
        SimpleDataTypeDef simpleUdt = (SimpleDataTypeDef) udtDef;
        GspBizEntityElement rez = new GspBizEntityElement(){{
            setCode(code);
            setName(name);
            setLabelID(labelId);
            setIsUdt(true);
            setUdtID(udtId);
            setUdtName(udtDef.getName());
            setObjectType(simpleUdt.getObjectType());
            setMDataType(simpleUdt.getMDataType());
            setLength(simpleUdt.getLength());
            setPrecision(simpleUdt.getPrecision());
        }};

        rez.setID(id);
        switch(simpleUdt.getObjectType()) {
            case None:
                break;
            case Enum:
                rez.setEnumIndexType(EnumIndexType.Integer);
                rez.setContainEnumValues(simpleUdt.getContainEnumValues().clone());
                break;
            default:
                throw BusinessEntityException.createException(BusinessEntityErrorCodeEnum.GSP_BEMODEL_BUSINESS_ENTITY_0012, simpleUdt.getObjectType().toString());
        }

        rez.getChildElements().add(new GspBizEntityElement(){{
            setID(UUID.randomUUID().toString());
            setLabelID(labelId + "_" + simpleUdt.getContainElements().get(0).getLabelID());
            setCode(code + "_" + simpleUdt.getContainElements().get(0).getCode());
            setIsRef(false);
            setObjectType(GspElementObjectType.None);
            setMDataType(simpleUdt.getMDataType());
            setLength(simpleUdt.getLength());
            setPrecision(simpleUdt.getPrecision());
        }});

        rez.getMappingRelation().add(new MappingInfo(){{
            setKeyInfo(rez.getChildElements().get(0).getID());
            setValueInfo(rez.getUdtID());
        }});
        return rez;
    }

    ///#endregion

    //region 生成构件和代码
    public static GspMetadata createCompCode(String path, String bizObjectId, String nodeCode,
        boolean isChild, GspBusinessEntity be, BizOperation operation) {
        //生成构件元数据
        GspMetadata compMeta = ComponentGenerator.getInstance().createCompByOperation(
            operation, path, be.getCode(), isChild, nodeCode, bizObjectId);
        operation.setComponentId(compMeta.getHeader().getId());
        operation.setComponentName(compMeta.getHeader().getCode());
        //生成java代码
        JavaCodeFileGenerator javaCodeFileGenerator = new JavaCodeFileGenerator(path, be);
        javaCodeFileGenerator.createJavaCodeFile(operation, isChild, nodeCode);
        return compMeta;
    }

    public static String getCodePath(String projectpath, GspMetadata compMetaData) {
        IMetadataContent content = compMetaData.getContent();
        String javaClass = ((GspComponent) content).getMethod().getClassName();

        String str = ManagerUtils.getRalativePath(
            SpringBeanUtils.getBean(MetadataProjectService.class).getProjPath(projectpath));
        str = str.replace("/", "\\");

        javaClass = javaClass.replace(".", "\\");
        String filePath = str + "\\java\\code\\comp\\src\\main\\java\\" + javaClass +".java";
        filePath = filePath.replaceAll("\\\\", Matcher.quoteReplacement(File.separator));
        filePath = filePath.replaceAll("/", Matcher.quoteReplacement(File.separator));
        return filePath;
    }
    // 获取是工程类型（生成型工程 or 解析型工程）
    public static ProcessMode getProjectProcessMode(String path) {
        MetadataProjectService service = getMetadataProjectService();
        return service.getProcessMode(getProjPath(path));
    }

    // 生成pom文件
    public static void generatePom(String path, String bizEntityName) {
        GenerateService service = getGenerateService();
        try {
            service.generate(getProjPath(path));
        } catch (Exception e) {
            throw BusinessEntityException.createException(BusinessEntityErrorCodeEnum.GSP_BEMODEL_BUSINESS_ENTITY_0013, e, bizEntityName);
        }
    }

    //endregion
}
